# -*- coding: utf-8 -*-

import requests
import json

import time
import random
import hmac
from hashlib import sha1
import base64
import uuid


def get_sign(secret, appkey, senid, nonce, content, timestamp):
    # 生成并返回签名
    param = 'a=services&l=v1&p=open&k=' + appkey + '&i=' + \
        senid + '&n=' + nonce + '&t=' + timestamp + '&f=' + content
    hmac_code = hmac.new(secret.encode(), param.encode(), sha1).digest()
    return base64.b64encode(hmac_code).decode()


def send_request(request_url, senid, appkey, app_secret, token, tin, method, content):
    """
    调用诺诺开放平台API
    发送HTTP POST请求 <同步>
    """
    timestamp = str(int(time.time()))  # 时间戳
    nonce = str(random.randint(10000, 1000000000))  # 随机正整数
    sign = get_sign(app_secret, appkey, senid, nonce, content, timestamp)  # 签名

    request_url = request_url + '?senid=' + senid + '&nonce=' + \
        nonce + '&timestamp=' + timestamp + '&appkey=' + appkey
    head = {'Content-type': 'application/json'}
    head.update({'X-Nuonuo-Sign': sign})
    head.update({'accessToken': token})
    head.update({'userTax': tin})
    head.update({'method': method})
    requestdata = content.encode("utf-8")

    print('request_url:', request_url)
    print('requestdata:', requestdata)
    print('head:', head)

    r = requests.post(request_url, data=requestdata, headers=head)
    return r.text

# 调用方法:
# 初始化时, 设置nuonuo参数, request_url, appkey, app_secret, token, tin
# request_url: 固定值, 来自于配置文件,
# appkey: 绑定公司, 一次申请后, 以后不在变了,
# app_secret: 绑定公司, 一次申请后, 以后不在变了,
# token: 绑定公司, 可以重新获取,
# tin: 绑定公司 税号
#


def access_token(refresh_token, client_id, client_secret):
    request_url = 'https://open.nuonuo.com/accessToken'

    head = {'Content-type': 'application/x-www-form-urlencoded;charset=UTF-8'}

    content = {
        'refresh_token': refresh_token,
        'client_id': client_id,
        'client_secret': client_secret,
        'grant_type': 'refresh_token'
    }

    # body = json.dumps(content)
    # requestdata = body.encode("utf-8")

    # print('request_url:', request_url)
    # print('requestdata:', requestdata)
    # print('head:', head)

    r = requests.post(request_url, data=content, headers=head)
    print('r', r)
    print('r.text:', r.text,  type(r.text))

    res = json.loads(r.text)
    print('res:', res,  type(res))

    # {'error_description': 'Incorrect refreshToken[2cda5b3c0b62f0a55443b86abc66c49d]',
    #  'error': '070314'}

    return res


class Nuonuo(object):
    def __init__(self, request_url, appkey, app_secret, token, tin):
        self.request_url = request_url
        self.appkey = appkey
        self.app_secret = app_secret
        self.token = token
        self.tin = tin

    def call_request(self, method, content):
        request_url = self.request_url
        appkey = self.appkey
        app_secret = self.app_secret
        token = self.token
        tin = self.tin

        node = uuid.getnode()
        senid = str(uuid.uuid1(node=node))
        senid = ''.join(senid.split('-'))

        body = json.dumps(content)
        return send_request(request_url, senid, appkey, app_secret,
                            token, tin, method, body)

    #
    # 已经调试完成的接口
    #

    def requestBillingNew(self, content):
        # 请求开具发票接口(2.0)
        api_method = 'nuonuo.electronInvoice.requestBillingNew'
        return self.call_request(api_method, content)

    def queryInvoiceResult(self, content):
        # 开票结果查询接口
        api_method = 'nuonuo.ElectronInvoice.queryInvoiceResult'
        return self.call_request(api_method, content)

    #  debuging...

    def invoiceCancellation(self, content):
        # 发票作废接口
        api_method = 'nuonuo.electronInvoice.invoiceCancellation'
        return self.call_request(api_method, content)

    #
    # 其他接口 todo, 待调试
    #

    def reInvoice(self, content):
        # 开票重试接口
        api_method = 'nuonuo.ElectronInvoice.reInvoice'
        return self.call_request(api_method, content)

    def queryInvoiceList(self, content):
        # 发票列表查询接口
        api_method = 'nuonuo.ElectronInvoice.queryInvoiceList'
        return self.call_request(api_method, content)

    def getInvoiceStock(self, content):
        # 企业发票余量查询接口
        api_method = 'nuonuo.ElectronInvoice.getInvoiceStock'
        return self.call_request(api_method, content)

    # 以下 红发票
    # 1. 购方 申请 ok?
    # 2. 购方 查询 ok?
    # 3. 购方 下载 ok?
    # 4. 销方  查询 / 下载 ??
    # 5. 销方 开红发票 ok

    def InvoiceRedApply(self, content):
        # 红字专用发票信息表申请接口
        api_method = 'nuonuo.ElectronInvoice.InvoiceRedApply'
        return self.call_request(api_method, content)

    def cancelInvoiceRedApply(self, content):
        # (红字专用发票信息表撤销接口)
        api_method = 'nuonuo.ElectronInvoice.'
        return self.call_request(api_method, content)

    def InvoiceRedQuery(self, content):
        # (红字专用发票信息表查询接口)
        api_method = 'nuonuo.ElectronInvoice.InvoiceRedQuery'
        return self.call_request(api_method, content)

    def downloadInvoiceRedApply(self, content):
        # (红字专用发票信息表下载接口)
        api_method = 'nuonuo.ElectronInvoice.downloadInvoiceRedApply'
        return self.call_request(api_method, content)

    # 以上 红发票

    def invoicePrintBatch(self, content):
        # (获取纸质发票批量打印编号接口)
        api_method = 'nuonuo.ElectronInvoice.invoicePrintBatch'
        return self.call_request(api_method, content)
